<script setup>
	import {
		computed,
		getCurrentInstance,
		onBeforeUnmount,
		onMounted, onUnmounted,
		ref,
		shallowRef,
		watch
	} from "vue";
	import QuillEditor from 'quill';
	import 'quill/dist/quill.core.css'
	import 'quill/dist/quill.snow.css'
	import 'quill/dist/quill.bubble.css'
	import {getToken} from "@/utils/auth";
	import {uploadRichImgApi} from "@/api/article/manage";
	import emitter from "@/utils/mitt";
	const { proxy } = getCurrentInstance();
	const emit = defineEmits();
	
	const props = defineProps({
		/* 编辑器的内容 */
		value: {
			type: String,
			default: "",
		},
		/* 高度 */
		height: {
			type: Number,
			default: null,
		},
		/* 高度 */
		minHeight: {
			type: Number,
			default: null,
		},
		maxHeight: {
			type: Number,
			default: null
		},
		/* 只读 */
		readOnly: {
			type: Boolean,
			default: false,
		},
		/* 上传文件大小限制(MB) */
		fileSize: {
			type: Number,
			default: 5,
		},
		/* 类型（base64格式、url格式） */
		type: {
			type: String,
			default: "url",
		},
		// 上传服务器地址
		url: {
			type: String,
			default: "/common/upload"
		}
	})
	
	const headers = {
		Authorization: "Bearer " + getToken()
	}
	
	const uploadUrl = import.meta.env.VITE_APP_BASE_API + props.url
	
	const Quill = shallowRef(null)
	const currentValue = ref(null)
	const options = shallowRef({
		theme: "snow",
		bounds: document.body,
		debug: "warning",
		modules: {
			// 工具栏配置
			toolbar: [
				["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线
				["blockquote", "code-block"],                    // 引用  代码块
				[{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表
				[{ indent: "-1" }, { indent: "+1" }],            // 缩进
				[{ size: ["small", false, "large", "huge"] }],   // 字体大小
				[{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题
				[{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色
				[{ align: [] }],                                 // 对齐方式
				["clean"],                                       // 清除文本格式
				["link", "image"]                       // 链接、图片
			],
			clipboard: {
			}
		},
		placeholder: "请输入内容",
		readOnly: props.readOnly,
	})
	const fileList = ref([])
	
	const controller = new AbortController()
	
	const init = () => {
		if(props.type === "url") {
			let toolbar = Quill.value.getModule("toolbar")
			toolbar.addHandler('image', (value) => {
				if(value) {
					document.getElementsByClassName('uploadButton')[0].click()
					console.log(1111);
				}
				else {
					Quill.value.format("image", false);
				}
			})
		}
		Quill.value.clipboard.dangerouslyPasteHTML(0, currentValue.value)
		Quill.value.on("text-change", (delta, oldDelta, source) => {
			const html = proxy.$refs.editor.children[0].innerHTML;
			const text = Quill.value.getText();
			const quill = Quill.value;
			currentValue.value = html;
			emit("input", html);
			emit("on-change", { html, text, quill });
		});
		Quill.value.on("text-change", (delta, oldDelta, source) => {
			emit("on-text-change", delta, oldDelta, source);
		});
		Quill.value.on("selection-change", (range, oldRange, source) => {
			emit("on-selection-change", range, oldRange, source);
		});
		Quill.value.on("editor-change", (eventName, ...args) => {
			emit("on-editor-change", eventName, ...args);
		})
		window.addEventListener("paste", async (evt) => {
			if(evt.clipboardData &&
				evt.clipboardData.files &&
				evt.clipboardData.files.length
			) {
				evt.preventDefault();
				let file = evt.clipboardData.files[0]
				let formData = new FormData()
				formData.append(`file`, file)
				const res = await uploadRichImgApi(formData);
				try {
					if(res.code === 200){
						if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
							return;
						}
						const reader = new FileReader()
						reader.readAsDataURL(file)
						reader.onload = async (e) => {
							Quill.value.insertEmbed(
								Quill.value.getSelection().index,
								"image",
								res.data.accessUrl
							)
							Quill.value.deleteText(
								Quill.value.getSelection().index - 1,
								1
							)
							Quill.value.setSelection(Quill.value.getSelection().index + 1, 0)
							emitter.emit('richTestFileList', [res.data])
						}
						reader.onerror = (error) =>reject(error)
					}
				}
				catch(e) {
					console.log(e);
				}
			}
		}, {
			signal: controller.signal
		})
	}
	
	const handleBeforeUpload = (file) => {
		const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
		const isJPG = type.includes(file.type);
		if (!isJPG) {
			proxy.$modal.msgError("上传头像图片只能是 JPG 格式!");
		}
		const isLt2M = file.size / 1024 / 1024 < 2;
		if (!isLt2M) {
			proxy.$modal.msgError("上传头像图片大小不能超过 2MB!");
		}
		return isJPG && isLt2M;
	}
	
	const handleUploadSuccess = (res, file) => {
		if (res.code == 200) {
			Quill.value.insertEmbed(
				Quill.value.getSelection().index,
				"image",
				res.data.accessUrl
			)
			Quill.value.setSelection(length + 1)
			fileList.value.push(res.data)
			emitter.emit("richTestFileList", fileList.value)
		} else {
			proxy.$modal.msgError(res.msg);
		}
	}
	
	const handleUploadError = () => {
		proxy.$modal.msgError("上传图片失败");
	}
	
	const getCurrentValue = () => {
		return currentValue.value
	}
	
	onMounted(() => {
		const editor = proxy.$refs.editor
		Quill.value = new QuillEditor(editor, options.value)
		init()
	})
	
	watch(() => props.value, (val) => {
		if (val !== currentValue.value) {
			currentValue.value = val === null ? "" : val;
			if(Quill.value) {
				Quill.value.clipboard.dangerouslyPasteHTML(0, val)
			}
		}
	}, { deep: true })
	
	const styles = computed(
		() => {
		let style = {};
		if (props.minHeight) {
			style.minHeight = `${props.minHeight}px`;
		}
		if (props.height) {
			style.height = `${props.height}px`;
		}
		if (props.maxHeight) {
			style.maxHeight = `${props.maxHeight}px`;
			style.overflow = 'auto';
		}
		return style;
	},)
	
	defineExpose({
		getCurrentValue
	})
	
	onBeforeUnmount(() => {
		controller.abort()
	})
	
</script>

<template>
	<div>
		<el-upload
			:action="uploadUrl"
			:before-upload="handleBeforeUpload"
			:on-success="handleUploadSuccess"
			:on-error="handleUploadError"
			name="file"
			:show-file-list="false"
			:headers="headers"
			style="display: none"
			ref="upload"
			accept="image/jpeg,image/jpg,image/png,image/svg"
			v-if="props.type === 'url'"
		>
			<el-button class="uploadButton" ref="uploadButton" v-if="props.type === 'url'" type="primary" style="display: none">select file</el-button>
		</el-upload>
		<div class="editor" ref="editor" :style="styles"></div>
	</div>
</template>

<style scoped lang="scss">
	.editor, .ql-toolbar {
		white-space: pre-wrap !important;
		line-height: normal !important;
	}
</style>
